package com.egg.common.rabbitmq.config;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.rabbitmq.client.Channel;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.EnableRabbit;
import org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;

import java.util.Objects;

/**
 * @desccription 自定义RabbitMQ的启动配置类，可以通过配置变量来控制启用、禁用
 */
@Profile({"prod", "test"})
@Slf4j
@EnableRabbit
@Configuration
public class RabbitMqConfig extends RabbitAutoConfiguration {

    /*
        在配置类中，排除默认的RabbitMQ自动配置类
        spring:
            autoconfigure:
                exclude: org.springframework.boot.autoconfigure.amqp.RabbitAutoConfiguration
     */


    /**
     * 消息发送日志切点
     */
    @Pointcut("execution(* com.egg.*.rabbitmq.sender..*.*(..))")
    public void senderPointCut() {
    }

    @Around("senderPointCut()")
    public void senderAround(ProceedingJoinPoint point) throws Throwable {
        String jsonParam = JSON.toJSONString(point.getArgs());
        String className = point.getTarget().getClass().getName();
        String methodName = point.getSignature().getName();
        log.debug("RabbitMQ 发送消息 类 {} 方法 {} 参数 {}", className, methodName, jsonParam);
        try {
            point.proceed();
            log.debug("RabbitMQ 发送消息 类 {} 方法 {} 执行完成 参数 {} ", className, methodName, jsonParam);
        } catch (Exception e) {
            log.error("RabbitMQ 发送消息 类 {} 方法 {} 执行失败 参数 {} 原因 {}", className, methodName, jsonParam, e);
            throw e;
        }
    }


    /**
     * 消息监听日志切点
     */
    @Pointcut("@annotation(org.springframework.amqp.rabbit.annotation.RabbitListener)")
    public void listenerPointCut() {
    }

    @Around("listenerPointCut()")
    public void listenerAround(ProceedingJoinPoint point) throws Throwable {
        Message message = null;
        Channel channel = null;
        for (Object object : point.getArgs()) {
            if (object instanceof Message) {
                message = (Message) object;

            } else if (object instanceof Channel) {
                channel = (Channel) object;
            }
        }
        if (Objects.isNull(message) || Objects.isNull(channel)) {
            //请求不满足时, 直接返回
            log.debug("RabbitMQ 监听消息 请求不满足 Message {}, Channel {}", message, channel);
            return;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(" MessageId[").append(message.getMessageProperties().getMessageId()).append("]")
                .append(" DeliveryTag[").append(message.getMessageProperties().getDeliveryTag()).append("]")
                .append(" Exchange[").append(message.getMessageProperties().getReceivedExchange()).append("]")
                .append(" routingKey[").append(message.getMessageProperties().getReceivedRoutingKey()).append("]")
                .append(" queue[").append(message.getMessageProperties().getConsumerQueue()).append("]");
        log.info("RabbitMQ 监听消息 队列 {} 入参 {}", sb.toString(), JSONObject.toJSON(new String(message.getBody())));
        try {
            point.proceed();
            log.info("RabbitMQ 监听消息 队列 {} 执行完成", sb.toString());
        } catch (Exception e) {
            log.error("RabbitMQ 监听消息 队列 {} 执行失败 原因 {}", sb.toString(), e);
            throw e;
        }
    }
}